#!/usr/bin/perl
# A simple Rot13 'encryption' bot

use Switch;
use strict;
use warnings;
use POE qw(Component::IRC);
use MIME::Base64;

#my $nickname = 'BusBot' . $$;
my $nickname = 'BusBot';
my $ircname = 'Hoebus\' Bot';
my $ircserver = 'irc.seed.net.tw';
my $port = 6667;

#my @channels = ( '#hoebus', '#wuliwala', '#chu' );
my @channels = ( '#hoebus');

# We create a new PoCo-IRC object and component.
my $irc = POE::Component::IRC->spawn( 
	nick => $nickname,
	server => $ircserver,
	port => $port,
	ircname => $ircname,
	) or die "Oh noooo! $!";

POE::Session->create(
	package_states => [
	'main' => [ qw(_default _start irc_001 irc_public irc_invite irc_msg) ],
	],
	heap => { irc => $irc },
	);

$poe_kernel->run();
exit 0;

sub _start {
    my ($kernel,$heap) = @_[KERNEL,HEAP];

# We get the session ID of the component from the object
# and register and connect to the specified server.
    my $irc_session = $heap->{irc}->session_id();
    $kernel->post( $irc_session => register => 'all' );
    $kernel->post( $irc_session => connect => { } );
    undef;
}

sub irc_001 {
    my ($kernel,$sender) = @_[KERNEL,SENDER];

# Get the component's object at any time by accessing the heap of
# the SENDER
    my $poco_object = $sender->get_heap();
    print "Connected to ", $poco_object->server_name(), "\n";

# In any irc_* events SENDER will be the PoCo-IRC session
    $kernel->post( $sender => join => $_ ) for @channels;
    undef;
}

sub irc_invite {
    my ($kernel,$sender,$who,$channel) = @_[KERNEL,SENDER,ARG0,ARG1];

    printf("irc_invite: who(%s) channel(%s)\n", $who, $channel);

    $kernel->post( $sender => join => $channel);
}

sub irc_msg {
    my ($kernel,$sender,$who,$where,$what) = @_[KERNEL,SENDER,ARG0,ARG1,ARG2];
    my $nick = ( split /!/, $who )[0];
    my $channel = $where->[0];

    message_parser(encode_base64(join(',', ("irc_msg", encode_base64($who,""), encode_base64($channel,""), encode_base64($what,""))), ""),
	    $kernel, $sender);
}

sub irc_public {
    my ($kernel,$sender,$who,$where,$what) = @_[KERNEL,SENDER,ARG0,ARG1,ARG2];
    my $nick = ( split /!/, $who )[0];
    my $channel = $where->[0];

    printf("who(%s) channel(%s) what(%s)\n", $who, $channel, $what);
    message_parser(encode_base64(join(',', ("irc_public", encode_base64($who,""), encode_base64($channel,""), encode_base64($what,""))), ""),
	    $kernel, $sender);

    undef;
}

# We registered for all events, this will produce some debug info.
sub _default {
    my ($event, $args) = @_[ARG0 .. $#_];
    my @output = ( "$event" );

    foreach my $arg ( @$args ) {
	if ( ref($arg) eq 'ARRAY' ) {
	    my @sub_output;
	    foreach my $sub_arg (@$arg) {
		push(@sub_output, encode_base64($sub_arg,"") );
	    }
	    push( @output, "[" . join(",", @sub_output ) . "]" );
	} else {
	    push ( @output, encode_base64($arg,"") );
	}
    }
    print STDOUT join ',', @output, "\n";

    message_parser(encode_base64(join(',', @output), ""));

    return 0;
}

sub message_parser {
    my $my_args = shift;
    my $kernel = shift;
    my $sender = shift;

    my $row;

    open(PARSER, "./message_parser.pl $my_args|");

    while ( $row = <PARSER> )
    {
	chomp($row);
	command_parser($row, $kernel, $sender);
    }

    close(PARSER);
}

sub command_parser {
    my $row = shift;
    my $kernel = shift;
    my $sender = shift;

    my @cols = split(",", $row);

    printf("row(%s)\n", $row);
    printf("switch(%s)\n", $cols[0]);
    
    switch ($cols[0])
    {
	case "privmsg" {
	    my $channel = decode_base64($cols[1]);
	    my $what = decode_base64($cols[2]);

	    if ( $sender )
	    {
		printf("command_parser: channel(%s) what(%s)\n", $channel, $what);
		$kernel->post( $sender => privmsg => $channel => $what );
	    }
	    else
	    {
		printf("sender not defined\n");
	    }
	}

	case "mode" {
	    my $channel = decode_base64($cols[1]);
	    my $mode = decode_base64($cols[2]);

	    $kernel->mode($channel, $mode);
	}

	case "invite" {
	    my $nick = decode_base64($cols[1]);
	    my $channel = decode_base64($cols[2]);

	    if ( $sender )
	    {
		$kernel->post( $sender => invite => $nick => $channel );
	    }
	    else
	    {
		printf("sender not defined\n");
	    }
	}
    }
}


